package com.ikingtech.framework.sdk.core.response;

import com.ikingtech.framework.sdk.base.model.PageResult;
import com.ikingtech.framework.sdk.context.security.Me;
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Locale;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public class ApiResult {

    private final MessageSource messageSource;

    private static final String SUCCESS_MESSAGE_KEY = "success";

    private static final String FAIL_MESSAGE_KEY = "fail";

    public <T> R<T> ok() {
        R<T> apiResult = new R<>();
        apiResult.setCode(0);
        apiResult.setData(null);
        apiResult.setMsg(this.messageSource.getMessage(SUCCESS_MESSAGE_KEY, null, Locale.forLanguageTag(Me.lang())));
        apiResult.setSuccess(true);
        apiResult.setTimestamp(LocalDateTime.now());
        return apiResult;
    }

    public <T> R<T> ok(T data) {
        R<T> apiResult = new R<>();
        apiResult.setCode(0);
        apiResult.setData(data);
        apiResult.setMsg(this.messageSource.getMessage(SUCCESS_MESSAGE_KEY, null, Locale.forLanguageTag(Me.lang())));
        apiResult.setSuccess(true);
        apiResult.setTimestamp(LocalDateTime.now());
        return apiResult;
    }

    public <T> R<List<T>> page(PageResult<T> pageResult) {
        return ok(pageResult.getPages(), pageResult.getTotal(), pageResult.getData());
    }

    public <T> R<List<T>> ok(long pages, long total, List<T> data) {
        R<List<T>> apiResult = new R<>();
        apiResult.setCode(0);
        apiResult.setMsg(this.messageSource.getMessage(SUCCESS_MESSAGE_KEY, null, Locale.forLanguageTag(Me.lang())));
        apiResult.setPages(pages);
        apiResult.setTotal(total);
        apiResult.setData(data);
        apiResult.setSuccess(true);
        apiResult.setTimestamp(LocalDateTime.now());
        return apiResult;
    }

    public <T> R<T> failed() {
        return failed(FAIL_MESSAGE_KEY);
    }

    public <T> R<T> failed(String msg) {
        R<T> apiResult = new R<>();
        apiResult.setCode(1);
        apiResult.setData(null);
        apiResult.setMsg(this.messageSource.getMessage(msg, null, msg, Locale.forLanguageTag(Me.lang())));
        apiResult.setSuccess(false);
        apiResult.setTimestamp(LocalDateTime.now());
        return apiResult;
    }

    public <T> R<T> validateFailed(BindingResult validateResult) {
        FieldError fieldError = validateResult.getFieldError();
        if (null == fieldError) {
            return failed();
        }
        String errorMessage = fieldError.getDefaultMessage();
        if (null == errorMessage) {
            return failed();
        }
        R<T> apiResult = new R<>();
        apiResult.setCode(1);
        apiResult.setData(null);
        Object[] arguments = fieldError.getArguments();
        if (null == arguments) {
            apiResult.setMsg(this.messageSource.getMessage(errorMessage, null, errorMessage, Locale.forLanguageTag(Me.lang())));
        } else {
            apiResult.setMsg(this.messageSource.getMessage(errorMessage, arguments, errorMessage, Locale.forLanguageTag(Me.lang())));
        }
        apiResult.setSuccess(false);
        apiResult.setTimestamp(LocalDateTime.now());
        return apiResult;
    }

    public void init() {
        if (ApiResultProxy.result() == null) {
            ApiResultProxy.accept(this);
        }
    }
}
